
#-----------------------------------------------------------------
# Imports
import bpy
import math
import mathutils

from myxml import *
from tags import *
    
#---------------------------------------------

# Obj should be an armature object
def write(obj, filename):
    
    if(obj.type != 'ARMATURE'):
        print('Anim: selected object not an armature')
        return

    file = open(filename, 'w')

    def w(text) :
        file.write(text)
    
    write_armature(obj, w)
    
    file.close()
    
    print("Object '" + obj.name + "' : skeleton exported")


# parameter w is a function that you call with string-data
# to write to a file
def write_armature(obj, w):   
   
   w(otag('skeleton'))
   
   # We only write the bones that have tags in the @skel property
   # of armature data   
   tags = set()
   prop = obj.data.get('@skel')
   if prop is not None:
       tags = set([t.strip() for t in prop.split(",")])   
   
   # Recursively write all root bones
   for bone in obj.pose.bones:
       if bone.parent is None: # it is a root bone
           write_bone(obj, bone.name, tags, w)
   
   w(ctag('skeleton'))


# Only export the bone if it has a tag that belongs to 'tags'
# Tags can be found on the pose bone
def write_bone(obj, bone_name, tags, w):
    
    # Currently not supported: exporting of tagged children under
    # a non-tagged parent (what would the desired result be, making
    # those children root?)
    if len(get_bone_tags(obj, bone_name).intersection(tags)) == 0:
        return 
    
    # We export the binding pose (not the animated pose)
    bone = obj.data.bones[bone_name]
    
    # Get the transformation matrix relative to the parent
    m = mathutils.Matrix()            
    if bone.parent is not None:
        m = bone.parent.matrix_local.inverted()
    m = m * bone.matrix_local
    
    # Make the bone-space use the Z-axis as the "up" axis 
    # (consistent with the scene).--> OOPS, not needed
    #corr1 = mathutils.Matrix.Rotation(math.radians(-90.0),4,'X')
    #corr2 = mathutils.Matrix.Rotation(math.radians(90.0),4,'X')    
    # Read from right to left
    #m = corr2 * m * corr1
    
    w(otag('bone', [('name', bone.name)]))
    
    # We do not export scale, because the binding pose is "at scale 1"     
    location = m.to_translation() # float array [3]
    rotation = m.to_quaternion() # float array [4], w,x,y,z
 
    w(octag('loc', zip('xyz', location)))
    w(octag('rot', zip('wxyz', rotation)))        
    
    if len(bone.children) > 0:
        w(otag('children'))
        
        for child in bone.children:
            write_bone(obj, child.name, tags, w)
        
        w(ctag('children'))
    
    w(ctag('bone')) 
    
    